﻿using NullTodoList.Properties;
using System;
using System.Windows.Forms;

namespace NullTodoList
{
    /// <summary>
    /// Форма создания либо редактирования заданий.
    /// </summary>
    public partial class frmAdding : Form
    {
        // Итоговая запись.
        private TodoItem item;
        // Тип операции (создание или изменение записи)
        private Boolean isEditing;

        #region ctor
        private frmAdding()
        {
            InitializeComponent();
            item = new TodoItem();
        }

        /// <summary>
        /// Конструктор формы.
        /// </summary>
        /// <param name="item">Редактируемое задание, либо создание если item == null.</param>
        public frmAdding(TodoItem item)
            : this()
        {
            // Определение типа операции.
            isEditing = item != null;
            // Загружаем все доступные теги в список.
            var rows = tagsTableAdapter.GetData();
            foreach (var row in rows)
                lbxTags.Items.Add(new Tag(row.id, row.text));
            // Изменяем состояние контролов в зависимости от типа операции.
            cbxCategory.SelectedIndex = 0;
            cbxCategory.Enabled = !isEditing;
            cbxPrioritet.SelectedIndex = 0;
            chkIsComplete.Visible = (isEditing && item.Category == TodoItem.CATEGORY_TASK);
            lblParents.Visible = !isEditing;
            cbxParents.Visible = !isEditing;
            // Заголовок в зависимости от типа операции.
            Text = (isEditing ? "Редактирование" : "Добавление новой") + " задачи";
            // Редактирование.
            if (isEditing)
            {
                // Копируем редактируемую задачу.
                this.item = (TodoItem)item.Clone();
                // Загружаем ее.
                LoadItem();
            }
            else
            {
                // Добавляем строку "Без привязки".
                var item2 = new TodoItem();
                item2.ID = TodoItem.INVALID_ITEM;
                item2.Text = "Без привязки";
                cbxParents.Items.Add(item2);
                // Заполняем список родительских заданий.
                var rows2 = itemsTableAdapter.GetData();
                foreach (var row in rows2)
                {
                    item2 = TodoItem.FromRow(row);
                    cbxParents.Items.Add(item2);
                    //cbxGroup.Items.Add(item2);
                }
                cbxParents.SelectedIndex = 0;
            }
        }
        #endregion

        #region Private methods
        /// <summary>
        /// Отображение параметров задания в форме.
        /// </summary>
        private void LoadItem()
        {
            cbxCategory.SelectedIndex = item.Category >> 1; // TODO: частный случай. для категории > 4 работать не будет.
            edtName.Text = item.Text;
            edtComment.Text = item.Comment;
            cbxPrioritet.SelectedIndex = item.Prioritet;
            chkIsComplete.Checked = item.IsComplete; 
            edtDateBegin.Value = item.DateBegin;
            if (item.Category == TodoItem.CATEGORY_PROCESS)
                edtLength.Text = TimeSpan.FromMinutes(item.Length).ToString();
            // Отмечаем задействованные теги.
            for (var i = 0; i < lbxTags.Items.Count; i++)
            {
                var tag = lbxTags.Items[i] as Tag;
                if (tag == null)
                    continue;
                if (item.Tags.Contains(tag.ID))
                    lbxTags.SetItemChecked(i, true);
            }
            // Отмечаем выбранные напоминания.
            for (var i = 0; i < lbxNotifies.Items.Count; i++)
            {
                var notify = (NotifyKind)(1 << i);
                if ((item.Notify & notify) != 0)
                    lbxNotifies.SetItemChecked(i, true);
            }
        }

        /// <summary>
        /// Созданное, либо отредактированное задание.
        /// </summary>
        public TodoItem Item
        {
            get { return item; }
        }

        /// <summary>
        /// В зависимости от категории задания отображается соответствующий интерфейс.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cbxCategory_SelectedIndexChanged(object sender, EventArgs e)
        {
            var index = cbxCategory.SelectedIndex;
            edtLength.Visible = index == 1;
            lblDateEnd.Visible = index == 1;
            switch (index)
            {
                case 0:
                    lblDateBegin.Text = "Крайний срок выполнения";
                    break;
                case 1:
                    lblDateBegin.Text = "Дата начала";
                    break;
                case 2:
                    lblDateBegin.Text = "Время оповещения";
                    break;
            }
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            // Конвертируем тип оповещения.
            var notify = NotifyKind.None;
            for (var i = 0; i < lbxNotifies.Items.Count; i++)
                if (lbxNotifies.GetItemChecked(i))
                    notify |= (NotifyKind)(1 << i);
            item.Category = 1 << cbxCategory.SelectedIndex;
            item.Text = edtName.Text;
            item.Comment = edtComment.Text;
            item.Prioritet = cbxPrioritet.SelectedIndex;
            item.IsComplete = isEditing ? chkIsComplete.Checked : false;
            item.DateBegin = edtDateBegin.Value;
            if (item.Category == TodoItem.CATEGORY_PROCESS)
            {
                TimeSpan time;
                if (TimeSpan.TryParse(edtLength.Text, out time))
                    item.Length = (Int32)time.TotalMinutes;
            }
            item.Notify = notify;
            if (!isEditing)
            {
                var parentItem = cbxParents.SelectedItem as TodoItem;
                item.Parent = parentItem != null ? parentItem.ID : TodoItem.INVALID_ITEM;
            }
        }

        /// <summary>
        /// Удаление тэга.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnDeleteTag_Click(object sender, EventArgs e)
        {
            var tag = lbxTags.SelectedItem as Tag;
            if (tag != null && MessageBox.Show(String.Format(Resources.MSG_DELETE_TAG, tag),
                Text, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                tagsTableAdapter.Delete(tag.ID);
                lbxTags.Items.Remove(tag);
            }
        }

        /// <summary>
        /// Добавление нового тэга.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAddTag_Click(object sender, EventArgs e)
        {
            var tagName = String.Empty;
            if (frmInputQuery.InputQuery("Добавить новый тэг", "Укажите имя тэга", ref tagName))
            {
                if (String.IsNullOrEmpty(tagName))
                {
                    MessageBox.Show(Resources.MSG_EMPTY_TAG_NAME,
                        Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                // Сохраняем тэг в БД.
                tagsTableAdapter.Insert(tagName);
                // Пытаемся достать добавленнный тэг.
                var rows = tagsTableAdapter.GetTagByName(tagName);
                // Ошибка при добавлении тэга.
                if (rows.Count == 0)
                {
                    MessageBox.Show(String.Format(Resources.MSG_ADD_TAG_ERROR, tagName),
                        Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                // Добавляем тэг в список доступных тэгов.
                var tag = new Tag(rows[0].id, rows[0].text);
                lbxTags.Items.Add(tag);
            }
        }

        private void lbxTags_SelectedIndexChanged(object sender, EventArgs e)
        {
            btnDeleteTag.Enabled = lbxTags.SelectedItem is Tag;
        }

        /// <summary>
        /// Контроль формата времени в окне ввода продолжительности процесса.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void edtLength_TextChanged(object sender, EventArgs e)
        {
            var maskedEdit = sender as MaskedTextBox;
            if (maskedEdit == null)
                return;
            var pos = maskedEdit.SelectionStart;
            var text = maskedEdit.Text;
            var hours = text.Substring(0, 2);
            if (Int32.Parse(hours) > 23)
                hours = "23";
            var minutes = text.Substring(3, 2);
            if (Int32.Parse(minutes) > 59)
                minutes = "59";
            var time = hours + ":" + minutes;
            if (!text.Equals(time))
            {
                maskedEdit.Text = time;
                maskedEdit.SelectionStart = pos;
            }
        }
        #endregion
    }
}
